//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2007
//
// Remove zoom level from the map.
//

# include "StdAfx.h"
# include "RemoveLevel.h"
# include "UndoRedo.h"
# include "MapView.h"
# include "Status.h"
# include "Scale.h"
# include "Levels.h"

class CRemoveLevelAction : public CEditAction {
  public:
	CRemoveLevelAction (size_t _cLevel) : m_cLevel (_cLevel) {}

	virtual void GetName (string_t & _str) const {
		_str.append ("Remove level ");
		_str.append (1, '0' + m_cLevel);
	}
	virtual cu_t CanUndo () const {return cuBackup;}
	virtual bool Do ();
	virtual void Undo () {}
	virtual void Redo () {}

  private:
	const size_t m_cLevel;
};

bool CRemoveLevelAction::Do () {
	CCritSec::CLock lock (g_cs);

	//
	// Modify header.
	//

	assert (m_cLevel < g_map.Levels.size ());
	g_map.Levels.erase (g_map.Levels.begin () + m_cLevel);

	//
	// Remove level elements.
	//
	for (size_t cKind = 0; cKind < rkMax; ++ cKind) {
		layer_t & layer = g_map.layers [cKind];
		rgns_t & rgns = layer.rgns;
		for (rgns_t::iterator iRgn = rgns.begin (); iRgn != rgns.end (); ++ iRgn) {
			rgn_t & rgn = * iRgn;
			if (rgn.IsDeleted () || rgn.IsWTR ())
				continue;

			if (rgn.uchEndLevel != 0 && rgn.uchEndLevel >= m_cLevel)
				-- rgn.uchEndLevel;

			size_t cElements = 0;

			// Check origins.
			for (size_t cOrigin = 0; cOrigin < rgn.origins.size (); ++ cOrigin) {
				rgn_origin_t & origin = rgn.origins [cOrigin];
				if (origin.bDeleted)
					continue;

				if (origin.cLevel == m_cLevel)
					origin.bDeleted = true;
				else {
					++ cElements;
					if (origin.cLevel > m_cLevel)
						-- origin.cLevel;
				}
			}
			
			// Check elements of the rgn.
			for (size_t cElement = 0; cElement < rgn.elements.size (); ++ cElement) {
				rgn_element_t & element = rgn.elements [cElement]; 
				if (element.bDeleted)
					continue;

				if (element.cLevel == m_cLevel)
					element.bDeleted = true;
				else {
					++ cElements;
					if (element.cLevel > m_cLevel)
						-- element.cLevel;
				}
			}

			if (cElements == 0)
				rgn.Delete (g_map);
		}
	}

	return true;
}

///////////////////////////////////////

void RemoveLevel (size_t _cLevel) {
	PerformEditAction (new CRemoveLevelAction (_cLevel));

	Refresh ();
	SetScaleStatus (g_fScale);
	MakeLevelsMenu ();
}
